/* * * * M A P V I S I O N   L I C E N S E  *****************************************************************
 *
 * This MapVision software is © Filip Zavadil 2013. It is licensed under the LGPL license.
 * This MapVision software dynamically links to unmodified Qt5 Library.
 *
 * The Qt5 Library is © 2013 Qt® and/or its subsidiary(-ies), and is licensed under the
 * GNU Lesser General Public License version 2.1 with Qt® LGPL exception version 1.1.
 * Qt5 library is free software; you can redistribute it and/or modify it under the terms of the
 * GNU Lesser General Public License, version 2.1, as published by the Free Software Foundation.
 * Qt5 library is provided “AS IS”, without WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR
 * IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT,
 * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
 *
 * As an additional permission to the GNU Lesser General Public License version 2.1, the object
 * code form of a “work that uses the Library” may incorporate material from a header file that is
 * part of the Library. You may distribute such object code under terms of your choice,
 * provided that: (i) the header files of the Library have not been modified; and (ii)
 * the incorporated material is limited to numerical parameters, data structure layouts, accessors,
 * macros, inline functions and templates; and (iii) you comply with the terms of Section 6 of the
 * GNU Lesser General Public License version 2.1.
 *
 * Moreover, you may apply this exception to a modified version of the Library, provided that such
 * modification does not involve copying material from the Library into the modified Library’s header
 * files unless such material is limited to (i) numerical parameters; (ii) data structure layouts;
 * (iii) accessors; and (iv) small macros, templates and inline functions of five lines or less in length.
 *
 * Furthermore, you are not required to apply this additional permission to a modified version of the Library.
 *
 * You should have received a copy of the GNU Lesser General Public License along with this package;
 * if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA

 * The source code for Qt 5.X SDK is available from Qt Project here:
 * http://download.qt-project.org/official_releases/qtcreator/2.7/2.7.0/qt-creator-2.7.0-src.zip.
 *
 * ****************************** M A P V I S I O N    S O F T W A R E  ************************************
 *
 * Author:       Filip Zavadil
 * Description:  Software for displaying and exporting map tiles.
 * The sources and executables of MapVision software are available:
 *    - from project hosting on CodePlex.com :   http://mapvision.codeplex.com
 *    - from GIT repositories on Gitorious.org:  https://gitorious.org/mapvision
 * Visit MapVision fanpage on Facebook.com:      https://www.facebook.com/pages/Mapvision/631827753513935
 *
 * *********************************************************************************************************
*/

#include "dialogexport.h"
#include "ui_dialogexport.h"
#include <QMessageBox>
#include <QFileDialog>
#include <QSettings>
#include <QtConcurrent/QtConcurrentRun>
#include <QMovie>
#include <QDebug>
#include <QFile>
#include <QTextStream>

DialogExport::DialogExport(QWidget *parent, MapView * map_) :
    QWidget(parent), map(map_), ui(new Ui::DialogExport)
{
    this->setWindowFlags( Qt::Window);
    ui->setupUi(this);

    connect(map,SIGNAL(mapUpdated(QPointF,int,int)),this,SLOT(mapRectHasChanged(QPointF,int,int)));
    connect(map->selection,SIGNAL(selectionChanged(QRectF)),this,SLOT(selectionRectHasChanged(QRectF)));
    connect(ui->lineEditNorth,SIGNAL(textChanged(QString)),this,SLOT(rectEdited(QString)));
    connect(ui->lineEditSouth,SIGNAL(textChanged(QString)),this,SLOT(rectEdited(QString)));
    connect(ui->lineEditWest,SIGNAL(textChanged(QString)),this,SLOT(rectEdited(QString)));
    connect(ui->lineEditEast,SIGNAL(textChanged(QString)),this,SLOT(rectEdited(QString)));
    connect(this,SIGNAL(mapIsSaved(QString,bool)),this,SLOT(mapHasSaved(QString,bool)));

    makeSel = parent->findChild<QAction*>("actionMake_Selection");
}

DialogExport::~DialogExport()
{
    delete ui;
}

void DialogExport::setTypeTitle(int index, QString title)
{
    ui->stackedWidget->setCurrentIndex(index);
    this->setWindowTitle(title);
    this->show();
}

void DialogExport::mapRectHasChanged(QPointF, int, int)
{
    if (ui->radioButtonAsDisplay->isChecked())
    {
        rect = map->getRectLonlat();
        this->updateRect();
    }
}

void DialogExport::selectionRectHasChanged(QRectF mapRectF)
{
    if (ui->radioButtonAsSelection->isChecked())
    {
        rect = mapRectF;
        this->updateRect();
    }
}

void DialogExport::on_radioButtonAsSelection_toggled(bool checked)
{
    if (!makeSel->isChecked()){
        makeSel->toggle();
    }

    if (checked)
    {
        rect = map->selection->getRectLonlat();
        this->updateRect();
    }
}

void DialogExport::on_radioButtonAsDisplay_toggled(bool checked)
{
    if (checked)
    {
        this->mapRectHasChanged(QPointF(10,10),10,30);
    }
}

void DialogExport::rectEdited(QString)
{
    if (ui->radioButtonSpecBellow->isChecked())
    {
        bool nOK,sOK,wOK,eOK;
        double north,south,west,east;

        north = ui->lineEditNorth->text().toDouble(&nOK);
        south = ui->lineEditSouth->text().toDouble(&sOK);
        west = ui->lineEditWest->text().toDouble(&wOK);
        east = ui->lineEditEast->text().toDouble(&eOK);

        if (nOK && sOK && wOK && eOK)
        {
            QPointF topLeft(west,north);
            QPointF bottomRight(east,south);
            rect = QRectF(topLeft,bottomRight);

            int height = zavaProj.lonlat2pixels(rect.bottomRight(),map->getZoom()).y()-zavaProj.lonlat2pixels(rect.topRight(),map->getZoom()).y();
            int width =  zavaProj.lonlat2pixels(rect.topRight(),map->getZoom()).x()-zavaProj.lonlat2pixels(rect.topLeft(),map->getZoom()).x();

            ui->spinBoxWidth->setValue(width);
            ui->spinBoxHeight->setValue(height);
        }
        else
        {
            QMessageBox msgBox;
            msgBox.setText(tr("This is not valid values"));
            msgBox.exec();
            return;
        }
    }
}

void DialogExport::updateRect()
{
    ui->lineEditNorth->setText(QString::number(rect.top()));
    ui->lineEditSouth->setText(QString::number(rect.bottom()));
    ui->lineEditWest->setText(QString::number(rect.left()));
    ui->lineEditEast->setText(QString::number(rect.right()));

    int height = zavaProj.lonlat2pixels(rect.bottomRight(),map->getZoom()).y()-zavaProj.lonlat2pixels(rect.topRight(),map->getZoom()).y();
    int width =  zavaProj.lonlat2pixels(rect.topRight(),map->getZoom()).x()-zavaProj.lonlat2pixels(rect.topLeft(),map->getZoom()).x();

    ui->spinBoxWidth->setValue(width);
    ui->spinBoxHeight->setValue(height);

}

void DialogExport::on_pushButton_clicked()
{
    int height = zavaProj.lonlat2pixels(rect.bottomRight(),map->getZoom()).y()-zavaProj.lonlat2pixels(rect.topRight(),map->getZoom()).y();
    int width =  zavaProj.lonlat2pixels(rect.topRight(),map->getZoom()).x()-zavaProj.lonlat2pixels(rect.topLeft(),map->getZoom()).x();

    ui->spinBoxWidth->setValue(width);
    ui->spinBoxHeight->setValue(height);


}

void DialogExport::on_spinBoxWidth_valueChanged(int arg1)
{
    if (ui->spinBoxWidth->hasFocus() && ui->checkBoxLockRatio->isChecked())
    {
        int height = zavaProj.lonlat2pixels(rect.bottomRight(),map->getZoom()).y()-zavaProj.lonlat2pixels(rect.topRight(),map->getZoom()).y();
        int width =  zavaProj.lonlat2pixels(rect.topRight(),map->getZoom()).x()-zavaProj.lonlat2pixels(rect.topLeft(),map->getZoom()).x();
        ratio = double(height)/double(width);
        ui->spinBoxHeight->setValue(arg1*double(ratio));
    }
}

void DialogExport::on_spinBoxHeight_valueChanged(int arg1)
{
    if (ui->spinBoxHeight->hasFocus() && ui->checkBoxLockRatio->isChecked())
    {
        int height = zavaProj.lonlat2pixels(rect.bottomRight(),map->getZoom()).y()-zavaProj.lonlat2pixels(rect.topRight(),map->getZoom()).y();
        int width =  zavaProj.lonlat2pixels(rect.topRight(),map->getZoom()).x()-zavaProj.lonlat2pixels(rect.topLeft(),map->getZoom()).x();
        ratio = double(height)/double(width);
        ui->spinBoxWidth->setValue(arg1/double(ratio));
    }
}


void DialogExport::on_pushButtonEportTo_clicked()
{
    QSettings settings;

    QFileDialog fileDialog;

    fileDialog.setDefaultSuffix(".png");

    QString fileName = fileDialog.getSaveFileName(this, tr("Save image map"), settings.value("save/mapImage").toString(),
                                                  tr("Images (*.png);;"
                                                     "Joint Photographic Experts Group (*.jpg);;"
                                                     "Tagged Image File Format (*.tiff);;"
                                                     "Windows Bitmap (*.bmp);;"
                                                     "All files (*.*)"));

    if(fileName!="")
    {
        settings.setValue("save/mapImage",fileName);

        int height = zavaProj.lonlat2pixels(rect.bottomRight(),map->getZoom()).y()-zavaProj.lonlat2pixels(rect.topRight(),map->getZoom()).y();
        int width =  zavaProj.lonlat2pixels(rect.topRight(),map->getZoom()).x()-zavaProj.lonlat2pixels(rect.topLeft(),map->getZoom()).x();

        QPoint topLeft = zavaProj.lonlat2pixels(rect.topLeft(),map->getZoom());

        QSize imageSize(ui->spinBoxWidth->value(),ui->spinBoxHeight->value());

        QImage newImage(imageSize,QImage::Format_ARGB32_Premultiplied);

        qDebug()<<"image size is: " << newImage.size();
        if (newImage.isNull()){
            QMessageBox msgBox;
            msgBox.setText(tr("Export area is too large!"));
            msgBox.exec();
            return;
        }

        QPainter * painter= new QPainter(&newImage);

        map->getScene()->render(painter,QRectF(QPoint(0,0),imageSize),QRectF(topLeft,QSize(width,height)),Qt::KeepAspectRatio);

        //map->render(painter,QRectF(QPoint(0,0),imageSize),QRectF(topLeft,QSize(width,height)).toRect(),Qt::KeepAspectRatio);

        // save with effects
        //QPixmap pix = QPixmap::grabWidget(map->get);
        //pix.save("out2.png");

        movie = new QMovie("images/loader.gif");
        ui->label_5->setMovie(movie);

        movie->start();
        ui->label_ImageSaveStatus->setText("Image is saving ...");
        QtConcurrent::run(this,&DialogExport::saveMap,newImage,fileName);

        // CREATE WORLDFILE
        if (ui->checkBoxCreateWorldFile->isChecked()){
            QRect rectPixels(topLeft,QSize(imageSize));
            this->createWorldFile(rectPixels,rect,fileName);
        }

    }
}

void DialogExport::mapHasSaved(QString text,bool isSaved)
{
    movie->stop();
    ui->label_5->clear();
    ui->label_ImageSaveStatus->setText(text);
    if (isSaved)
    {
        ui->label_5->setPixmap(QPixmap("images/checked.png"));

    }
    else
    {
        ui->label_5->setPixmap(QPixmap("images/cross.png"));
    }


}

bool DialogExport::saveMap(QImage image, QString filename)
{

    bool isSaved = image.save(filename);
    if (isSaved)
    {
        double ratio = double(image.height())/60.0;
        int width = image.width()/ratio;
        QString mess = "<a href=\"" + filename +"\"> <img src=\"" + filename +"\" height=\"60\" width=\""+QString::number(width)+"\"/></a><br/>\n";
        mess += "Image (<b>"+QString::number(image.width())+"x"+QString::number(image.height())+"</b>) was saved to: <code>"+filename+"</code><br>\n";
        mess += "<table border=1 bordercolor=\"solid black\" style=\"border-collapse:collapse; background-color:#FFFFCC\" cellpadding=\"1\" cellspacing=\"1\">"\
                "<tr>"\
                "<th align=\"center\" colspan=2>COORDINATES</th>\n"\
                "</tr><tr align=\"right\">"\
                "<th>North-West</th><td>"+zavaProj.lonlat2dms(rect.topLeft())+"</td>\n"\
                "</tr><tr align=\"right\">"\
                "<th>South-East</th><td>"+zavaProj.lonlat2dms(rect.bottomRight())+"</td>\n"\
                "</tr>"\
                "</table><br/>\n";
        map->sendMessagePublic(mess);
        emit mapIsSaved(tr("Image is saved ..."),true);
    }
    else
    {
        emit mapIsSaved(tr("Image is not saved !!! ..."),false);
    }
    return isSaved;

}

void DialogExport::createWorldFile(QRect pixelRect, QRectF lonlatRect,QString imgFilename )
{
    Q_UNUSED(lonlatRect)

    QPointF utmTopLeft = zavaProj.lonlat2UTM(rect.topLeft());

    QPointF utmBottomRight = zavaProj.lonlat2UTM(rect.bottomRight());

    double diffX = utmBottomRight.x() - utmTopLeft.x();

    double diffY = utmTopLeft.y() - utmBottomRight.y();

    double resX = diffX / pixelRect.size().width();
    double resY = diffY / pixelRect.size().height();


    QPointF coors = utmTopLeft; //+ QPointF(resX/2,resY/2);

    QString output = QString::number(resX,'f',16) + "\n" + "0\n-0\n" + QString::number(-resY,'f',16)+ "\n";
    output += QString::number(coors.x(),'f',9) + "\n" +QString::number(coors.y(),'f',9);

    // write WORLDFILE
    QString fileName = imgFilename;

    fileName.remove(imgFilename.size()-2,1);
    fileName+="w";

    QFile *textak =  new QFile(fileName);

    if (textak->open(QIODevice::ReadWrite)){
        QTextStream out(textak);
        out << output;
        QString mess = "The <i>worldfile</i> was saved to: <code>"+textak->fileName()+"</code></br>\n";
        map->sendMessagePublic(mess);
    } else {
    }

    textak->close();

}


